﻿using UnityEngine;
using System.Collections;

public class ChangeGravity : MonoBehaviour {
	public float rotationTime;
	public AnimationCurve curve = new AnimationCurve();
	public bool rotationAllowed = true;

	[HideInInspector]
	public bool rotationLocked = false;
	[HideInInspector]
	public bool changeCamera = false;
	private Vector3 rotDir;
	private float rotationSum;
	private float rotationStartTime, lastFrameRotation;
	private GameObject level;
	private float angleToRotate;

	// Use this for initialization
	void Start () {
		Screen.lockCursor = true;
		level = GameObject.Find("Level");
	}

	public void startRotation(Vector3 rotationDir) {
		startRotation (rotationDir, false);
	}

	public void startRotation(Vector3 rotationDir, bool ignorePermission, float angle) {
		if(!changeCamera && !rotationLocked) {
			if(!ignorePermission && !rotationAllowed)
				return;
			if(rotationDir == Vector3.up || rotationDir == Vector3.down)
				return;
			
			rotDir = rotationDir;
			changeCamera = true;
			lastFrameRotation = rotationStartTime = Time.time;
			rotationSum = 0;
			angleToRotate = angle;
		}
	}

	public void startRotation(Vector3 rotationDir, bool ignorePermission) {
		startRotation (rotationDir, ignorePermission, 90);
	}
	
	// Update is called once per frame
	void Update () {
		if(Input.GetButtonDown("Fire1") && !changeCamera && !rotationLocked) {
			Vector3 direction = transform.forward.normalized;
			Vector3[] directions = {Vector3.forward, Vector3.back,
									Vector3.left, Vector3.right,
									Vector3.up, Vector3.down};

			float currentMin = float.MaxValue;
			Vector3 lookDirection = Vector3.zero;
			foreach(Vector3 v in directions) {
				float angle = Vector3.Angle(v, direction);
				if(angle < currentMin) {
					currentMin = angle;
					lookDirection = v;
				}
			}

			if(lookDirection == Vector3.up || lookDirection == Vector3.down) {
				return;
			}

			startRotation(Vector3.Cross(Vector3.up, lookDirection));
		}

		if (changeCamera) {
			float currentTime = Time.time;

			float oldValue = curve.Evaluate((lastFrameRotation - rotationStartTime) / rotationTime);
			float newValue = curve.Evaluate((currentTime - rotationStartTime) / rotationTime);

			float angle = angleToRotate * (newValue - oldValue);
			lastFrameRotation = currentTime;

			// If rotation would overshoot, clip it to max angle
			if(rotationSum + angle > angleToRotate) {
				angle = angleToRotate - rotationSum;
			}

			level.transform.RotateAround(transform.position, rotDir, angle);
			rotationSum += angle;
			if(rotationSum >= angleToRotate || currentTime >= rotationStartTime + rotationTime) {
				changeCamera = false;
			}
		}
	}
}
